package kalambury.client;

import kalambury.KalamburyUtils;
import kalambury.srv.PlayerInfo;
import kalambury.srv.PlayerStatus;
import kalambury.srv.packets.*;

import java.awt.Image;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.Socket;
import java.util.ArrayList;
import java.util.List;

/**
 * Created with IntelliJ IDEA.
 * User: ufoq
 * Date: 20.11.12
 * Time: 00:18
 * To change this template use File | Settings | File Templates.
 */
public class GameConnection {

    public static interface GameConnectionEventsListener {
        public void onImageReceived(Image img);

        public void onPasswordSuggestionReceived(String playerName, String suggestion, boolean valid);

        public void onPlayersListReceived(List<PlayerInfo> players);

        public void onPlayerStatusReceived(PlayerStatus status, String additionalInfo);

        public void onDrawerChanged(String name);
    }

    private Socket clientSocket;
    private ObjectInputStream inStream;
    private ObjectOutputStream outStream;
    private String myName;
    private GameConnectionEventsListener eventsListener;
    private Object lockForEventsListener = new Object();
    private final ListenerThread listenerThread = new ListenerThread();

    public static GameConnection create(Socket clientSocket,
                                        String name, String pass) {
        try {
            GameConnection g = new GameConnection();
            g.clientSocket = clientSocket;
            g.outStream = new ObjectOutputStream(clientSocket.getOutputStream());
            g.inStream = new ObjectInputStream(clientSocket.getInputStream());
            pass= KalamburyUtils.getHash(pass);
            HelloPacket hello = new HelloPacket(name,pass);
            g.outStream.writeObject(hello);
            HelloResponsePacket hrp = (HelloResponsePacket) g.inStream.readObject();
            if (!hrp.success) {
                clientSocket.close();
                return null;
            }
            g.myName = name;
            g.listenerThread.start();
            return g;
        } catch (Exception e) {
            try {
                if (clientSocket != null)
                    clientSocket.close();
            } catch (Exception exx) {
            }
            e.printStackTrace();
        }
        return null;
    }

    private GameConnection() {
    }

    public String getMyName(){
        return myName;
    }

    public void setEventsListener(GameConnectionEventsListener el) {
        synchronized (lockForEventsListener) {
            eventsListener = el;
        }
    }

    public void disconnect() {
        try {
            listenerThread.stopRunning();
            if (clientSocket != null) {
                sendPacket(new ByePacket());
                clientSocket.close();
            }
        } catch (Exception e) {
        }
    }

    public void requestPlayerStatus() {
        CustomRequestPacket crp = new CustomRequestPacket(CustomRequestPacket.CustomRequestType.ResendPlayerStatus);
        sendPacket(crp);
    }

    public void requestPlayersList() {
        sendPacket(new CustomRequestPacket(CustomRequestPacket.CustomRequestType.ResendPlayersList));
    }

    public void sendImage(Image img) {
        sendPacket(new ImagePacket(img));
    }

    public void sendSuggestion(String s) {
        sendPacket(new SuggestionPacket(s));
    }

    private void sendPacket(Packet p) {
        try {
            if (outStream != null)
                outStream.writeObject(p);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private class ListenerThread extends Thread {
        private boolean running;

        public synchronized void stopRunning() {
            running = false;
        }

        public synchronized void start() {
            super.start();
            running = true;
        }

        public synchronized boolean isRunning() {
            return running;
        }

        @Override
        public void run() {
            try {
                while (isRunning()) {
                    Packet pkt = (Packet) inStream.readObject();
                    if (pkt != null) {
                        synchronized (lockForEventsListener) {
                            handlePacket(pkt);
                        }
                    }
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }

        private synchronized void handlePacket(Packet pkt) {
            if (eventsListener == null)
                return;
            if (pkt instanceof PlayerListPacket) {
                PlayerListPacket plp = (PlayerListPacket) pkt;
                eventsListener.onPlayersListReceived(plp.players);
            } else if (pkt instanceof ImagePacket) {
                ImagePacket ip = (ImagePacket) pkt;
                eventsListener.onImageReceived(ip.getImageFromData());
            } else if (pkt instanceof PlayerStatusPacket) {
                PlayerStatusPacket psp = (PlayerStatusPacket) pkt;
                eventsListener.onPlayerStatusReceived(psp.playerStatus, psp.additionalInfo);
            } else if (pkt instanceof SuggestionResultPacket) {
                SuggestionResultPacket sp = (SuggestionResultPacket) pkt;
                eventsListener.onPasswordSuggestionReceived(sp.author, sp.suggestionString, sp.valid);
            } else if (pkt instanceof DrawerChangedPacket) {
                DrawerChangedPacket sp = (DrawerChangedPacket) pkt;
                eventsListener.onDrawerChanged(sp.drawerName);
            }
        }
    }
}
